home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume4 / game_reg < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  14.8 KB

  1. Subject: GR - A Game Regulator
  2. Reply-To: mcooper@usc-oberon.arpa
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 4, Issue 113
  7. Submitted by: talcott!usc-oberon.ARPA:mcooper
  8.  
  9. #!/bin/sh
  10. # This is a shell archive, meaning:
  11. # 1. Remove everything above the #!/bin/sh line.
  12. # 2. Save the resulting text in a file.
  13. # 3. Execute the file with /bin/sh (not csh) to create the files:
  14. #    README
  15. #    Makefile
  16. #    gr.control
  17. #    gr.c
  18. #    gr.h
  19. #    logfile.c
  20. # This archive created: Mon May  5 13:14:10 1986
  21. # By:    Michael A. Cooper (USC Computing Services, Los Angeles)
  22. export PATH; PATH=/bin:$PATH
  23. echo shar: extracting "'README'" '(1915 characters)'
  24. if test -f 'README'
  25. then
  26.     echo shar: over-writing existing file "'README'"
  27. fi
  28. cat << \SHAR_EOF > 'README'
  29.  
  30.         G R  -  A   G A M E   R E G U L A T O R
  31.  
  32.                  Revision 1.16
  33.  
  34.  
  35.     GR is used to regulate game playing.  It checks various system
  36. facts such as the number of logged in users, and the system load average
  37. against a central control file to determine whether it is okay to play
  38. a requested game.  It also lets you select a priority (see setpriority(2))
  39. at which the game will run.  See the (enclosed) manual for more details.
  40.     
  41.     GR was formerly called "gsh" from which the base code was written
  42. at Reed College by a person who wishes to remain anonymous.  I "adopted"
  43. it and have extensively modified the code.  
  44.  
  45.     We are currently running GR on 4 of our VAX 750's running 4.2BSD.
  46. I suspect that the code should run without problems under 4.3BSD.  As for
  47. System V, I'm sure some minimal modifications will have to be made, but
  48. as yet, I have not tried porting it.
  49.  
  50.     To install GR, edit gr.h and Makefile to tailor to your system.
  51. The comments supplied therein, should suffice.  Then run "make gr" to
  52. compile GR.  You should have no errors.  Now edit the "gr.control" file
  53. to set your local system parameters.  Next run "make create" to 
  54. create the appropriate directory and support files.  Run "make dolink"
  55. if you wish to have most of the standard 4.2 games put under the regulator;
  56. otherwise, you can link them by hand.
  57.  
  58.     I'd appreciate any bugs/comments you wish to pass along.
  59.  
  60.                     Mike Cooper
  61.  
  62.  
  63. +-----------------------------------------------------------------------------+
  64. | Michael Cooper            UUCP: ...!{uscvax, sdcrdcf, scgvaxd,      |
  65. | University Computing Services           engvax, smeagol}!usc-oberon!mcooper |
  66. | University of Southern Cal.     BITNET: mcooper@uscvaxq, mcooper@jaxom      |
  67. | Los Angeles, Ca.   90089-0251     ARPA: mcooper@usc-oberon.arpa,          |
  68. | (213) 743-3462                mcooper@usc-eclc.arpa            |
  69. +-----------------------------------------------------------------------------+
  70. SHAR_EOF
  71. echo shar: extracting "'Makefile'" '(1506 characters)'
  72. if test -f 'Makefile'
  73. then
  74.     echo shar: over-writing existing file "'Makefile'"
  75. fi
  76. cat << \SHAR_EOF > 'Makefile'
  77. #
  78. # Makefile for Game Regulator.
  79. #
  80. # $Header: Makefile,v 1.1 86/05/05 13:13:34 mcooper Exp $
  81. #
  82.  
  83. #
  84. # GAMEDIR - This is where the symbolic links are to be placed.
  85. #        Should be /usr/games.
  86. #
  87. GAMEDIR = /usr/games
  88.  
  89. #
  90. # HIDEDIR - Name of directory to hide the actual executables
  91. #
  92. HIDEDIR = $(GAMEDIR)/.hide
  93.  
  94. # GROUP - This group has read/execute permissions on HIDEDIR and owns
  95. #      the Game Regulator which is setgid to GROUP.
  96. #
  97. GROUP = play
  98.  
  99. #
  100. # NAME - Name of Game Regulator in GAMEDIR.  I have it set to ".gr"
  101. #      so it doesn't show up with ls(1) by default.
  102. #
  103. NAME = .gr
  104.  
  105. #
  106. # GAMES - The games in the original GAMEDIR to be put under regulation.
  107. #
  108. GAMES = adventure backgammon btlgammon canfield chess cribbage fish\
  109.     hangman mille monop rain rogue sail snake teachgammon trek \
  110.     worm worms wump zork
  111.  
  112. OBJS = gr.o logfile.o
  113.  
  114. gr: $(OBJS)
  115.     cc -s $(OBJS) -o gr
  116.  
  117. dbx: $(OBJS)
  118.     cc -g $(OBJS) -o gr -llocal
  119.  
  120. .c.o:
  121.     cc -c $*.c
  122.  
  123. $(OBJS): gr.h
  124.  
  125. install: gr
  126.     install -m 2751 -g $(GROUP) gr $(GAMEDIR)/$(NAME)
  127.  
  128. create:
  129.     -mkdir $(HIDEDIR)
  130.     chgrp $(GROUP) $(HIDEDIR)
  131.     chmod 770 $(HIDEDIR)
  132.     cp gr.control $(GAMEDIR)/lib
  133.     touch $(GAMEDIR)/lib/gr.log
  134.     chgrp $(GROUP) $(GAMEDIR)/lib/gr.control $(GAMEDIR)/lib/gr.log
  135.     chmod 664 $(GAMEDIR)/lib/gr.control $(GAMEDIR)/lib/gr.log
  136.  
  137. dolink: dolink.sh
  138.     sed s#HIDEDIR#$(HIDEDIR)# dolink.sh |\
  139.         sed s#GAMEDIR#$(GAMEDIR)# |\
  140.         sed s#NAME#$(NAME)# > dolink
  141.     chmod +x dolink
  142.     dolink $(GAMES)
  143.  
  144. clean:
  145.     rm -f *.o log dolink
  146.  
  147. shar:
  148.     shar README Makefile gr.control *.[ch] > shar.out
  149. SHAR_EOF
  150. echo shar: extracting "'gr.control'" '(582 characters)'
  151. if test -f 'gr.control'
  152. then
  153.     echo shar: over-writing existing file "'gr.control'"
  154. fi
  155. cat << \SHAR_EOF > 'gr.control'
  156. #
  157. # Game Regulator Control File
  158. #
  159. # Note - The last line contains the default parameters for any file NOT listed.
  160. #
  161. #     Name         - Name of game in /usr/games.         (string)
  162. #    Load         - Maximum load average.          (floating point)
  163. #    Users         - Maximum number of users.          (integer)
  164. #    Priority    - Priority game will run at.
  165. #              See setpriority(2).            (integer)
  166. #
  167. #         Maximum
  168. # Name           Load    Users   Priority
  169. #--------------------------------------
  170. rogue        4.0    8    0
  171. arogue        4.0    8    0
  172. srogue        4.0    8    0
  173. urogue        4.0    8    0
  174. ourogue        4.0    8    0
  175. hack        4.0    8    5
  176. sail        4.0    8    0
  177. empire        4.0    8    0
  178. default        5.0    8    0
  179. SHAR_EOF
  180. echo shar: extracting "'gr.c'" '(5975 characters)'
  181. if test -f 'gr.c'
  182. then
  183.     echo shar: over-writing existing file "'gr.c'"
  184. fi
  185. cat << \SHAR_EOF > 'gr.c'
  186. #ifndef lint
  187. static char *RCSid = "$Header: gr.c,v 1.16 86/04/26 17:30:53 mcooper Exp $";
  188. #endif
  189.  
  190. /*
  191.  *------------------------------------------------------------------
  192.  *
  193.  * $Source: /usr/src/local/gr/RCS/gr.c,v $
  194.  * $Revision: 1.16 $
  195.  * $Date: 86/04/26 17:30:53 $
  196.  * $State: Exp $
  197.  * $Author: mcooper $
  198.  * $Locker: mcooper $
  199.  *
  200.  *------------------------------------------------------------------
  201.  *
  202.  * Michael Cooper (mcooper@usc-oberon.arpa)
  203.  * University Computing Services,
  204.  * University of Southern California,
  205.  * Los Angeles, California,   90089-0251
  206.  * (213) 743-3469
  207.  *
  208.  *------------------------------------------------------------------
  209.  * $Log:    gr.c,v $
  210.  * Revision 1.16  86/04/26  17:30:53  mcooper
  211.  * This version adds a new field to the gr.control
  212.  * file that specifies the priority that the game will
  213.  * run at.
  214.  * 
  215.  * Revision 1.15  86/03/25  18:50:08  mcooper
  216.  * Added #ifdef LOGFILE.
  217.  * 
  218.  * Revision 1.14  86/03/25  15:48:49  mcooper
  219.  * New headers.
  220.  * 
  221.  *------------------------------------------------------------------
  222.  */
  223.  
  224. #include <stdio.h>
  225. #include <signal.h>
  226. #include <sys/wait.h>
  227. #include <sys/types.h>
  228. #include <sys/stat.h>
  229. #include <sys/time.h>
  230. #include <sys/resource.h>
  231. #include <utmp.h>
  232. #include <nlist.h>
  233. #include "gr.h"
  234.  
  235.  
  236. static int ufd = 0;
  237. static int max_users;
  238. static int priority = 0;
  239. static lfd = 0;
  240. static double avenrun[3];
  241. static double max_load;
  242. static struct utmp buf;
  243. static struct nlist nl[] = {
  244.     { "_avenrun" },
  245.     { "" },
  246. };
  247.  
  248. int was_tod;
  249. int was_load;
  250. int was_users;
  251. char *rindex();
  252. long time();
  253.  
  254. main(argc, argv)
  255. int argc;
  256. char **argv;
  257. {
  258.     char *game = rindex(argv[0], '/');
  259.  
  260.     if (game == 0)
  261.         game = argv[0];
  262.     else
  263.         game++;    /* Skip the '/' */
  264.     setup(game);
  265.     if(checkfor(NOGAMING))
  266.         exit(2);
  267.     if (tod() || users() || load()) {
  268.         fprintf(stderr, "Sorry, no games now.\n");
  269.         if (was_load)
  270.             fprintf(stderr, 
  271.                 "The system load is greater than %.2lf.\n",
  272.                 max_load);
  273.         if (was_users)
  274.             fprintf(stderr, 
  275.                 "There are more than %d users logged in.\n",
  276.                 max_users);
  277.         if (was_tod)
  278.             fprintf(stderr, 
  279. "Game playing is not permitted between %d00 and %d00 hours on weekdays.\n", 
  280.                 MORNING, EVENING);
  281.         exit(1);
  282.     }
  283. #ifdef LOGFILE
  284.     logfile(game);
  285. #endif
  286.     play(game, argv);
  287. }
  288.  
  289. play(game, args)
  290. char *game;
  291. char **args;
  292. {
  293.     int pid;
  294.     char tmp[128];
  295.  
  296.     switch (pid = fork()) {
  297.     case -1:
  298.         fprintf(stderr, "Cannot fork.\n");
  299.         exit(1);
  300.     case 0:
  301.         strcpy(tmp, HIDEDIR);
  302.         strcat(tmp, "/");
  303.         strcat(tmp, game);
  304.         signal(SIGINT, SIG_DFL);
  305.         signal(SIGQUIT, SIG_DFL);
  306.         signal(SIGTSTP, SIG_DFL);
  307.         setuid(getuid());
  308.         if(setpriority(PRIO_PROCESS, 0, priority) < 0) {
  309.             perror("setpriority");
  310.             exit(1);
  311.         }
  312.         execv(tmp, args);
  313.         perror(tmp);
  314.         exit(1);
  315.     }
  316.     for (;;) {
  317.         sleep(60);
  318.         if (load() || users() || tod()) {
  319.             warn(0);
  320.             sleep(60);
  321.             if (reprieve())
  322.                 continue;
  323.             sleep(60);
  324.             if (reprieve())
  325.                 continue;
  326.             warn(1);
  327.             sleep(60);
  328.             if (reprieve())
  329.                 continue;
  330.             warn(2);
  331.             sleep(60);
  332.             if (reprieve())
  333.                 continue;
  334.             blast(pid);
  335.         }
  336.     }
  337. }
  338.  
  339. reprieve()
  340. {
  341.     static char mess[] = "\rYou have a reprieve.  Continue playing.\r\n";
  342.  
  343.     if (load() || users() || tod())
  344.         return (0);
  345.     write(2, mess, sizeof(mess));
  346.     return (1);
  347. }
  348.  
  349. warn(which)
  350. int which;
  351. {
  352.     static char buff[512];
  353.     static char *mesg = "to save your game.  If you do not leave\r\n\
  354. the game within this period, your game will be terminated.\r\n";
  355.     static char *t[3] = {
  356.         "4 minutes ",
  357.         "2 minutes ",
  358.         "1 minute "
  359.     };
  360.  
  361.     if (was_load)
  362.         sprintf(buff, "\rThe system load is greater than %.2lf.\r\n",
  363.             max_load);
  364.     if (was_users)
  365.         sprintf(buff, "\rThere are more than %d users logged in.\r\n",
  366.             max_users);
  367.     if (was_tod)
  368.         sprintf(buff, "\rGame time is over.\r\n");
  369.     strcat(buff, "You have ");
  370.     strcat(buff, t[which]);
  371.     strcat(buff, mesg);
  372.     write(2, buff, strlen(buff));
  373. }
  374.  
  375. blast(pid)
  376. int pid;
  377. {
  378.     static char mess[] = "\rYour game is forfeit.\r\n";
  379.  
  380.     write(2, mess, sizeof(mess));
  381.     kill(pid, SIGHUP);
  382.     sleep(60);
  383.     kill(pid, SIGKILL);
  384. }
  385.  
  386. death(n)
  387. int n;
  388. {
  389.     union wait status;
  390.  
  391.     if (wait3(&status, WNOHANG | WUNTRACED, (char *)0) == 0) {
  392.         return;
  393.     }
  394.     if (status.w_stopval == WSTOPPED) {
  395.         signal(SIGTSTP, SIG_DFL);
  396.         kill(getpid(), SIGTSTP);
  397.         signal(SIGTSTP, SIG_IGN);
  398.         return;
  399.     } else
  400.         exit(0);
  401. }
  402.  
  403.  
  404. setup(game)
  405. char *game;
  406. {
  407.     char tmp[16];
  408.     char lbuf[BUFSIZ];
  409.     int n;
  410.     FILE *list;
  411.  
  412.     if ((ufd = open("/etc/utmp", 0)) < 0) {
  413.         perror("/etc/utmp");
  414.         exit(1);
  415.     }
  416.     if ((lfd = open("/dev/kmem", 0)) < 0) {
  417.         perror("/dev/kmem");
  418.         exit(1);
  419.     }
  420.     nlist("/vmunix", nl);
  421.     if (nl[0].n_type == 0) {
  422.         perror("/vmunix");
  423.         exit(1);
  424.     }
  425.     if ((list = fopen(CONTROL, "r")) == NULL) {
  426.         perror(CONTROL);
  427.         exit(1);
  428.     }
  429.     while (fgets(lbuf, sizeof(lbuf), list)) {
  430.         if(lbuf[0] == COMMENT)
  431.             continue;
  432.         sscanf(lbuf, "%s%lf%d%d", 
  433.             tmp, &max_load, &max_users, &priority);
  434.         if (strcmp(tmp, game) == 0)
  435.             break;
  436.     }
  437.     fclose(list);
  438.     signal(SIGCHLD, death);
  439.     signal(SIGINT, SIG_IGN);
  440.     signal(SIGQUIT, SIG_IGN);
  441.     signal(SIGTSTP, SIG_IGN);
  442. }
  443.  
  444. load()
  445. {
  446.     lseek(lfd, (long)nl[0].n_value, 0);
  447.     read(lfd, avenrun, sizeof(avenrun));
  448.     return (was_load = (avenrun[1] >= max_load));
  449. }
  450.  
  451. users()
  452. {
  453.     char tmp[32];
  454.     int count = 0;
  455.     long l = time((long *)0);
  456.     struct stat sbuf;
  457.  
  458.     lseek(ufd, (long)0, 0);
  459.     while (read(ufd, &buf, sizeof(buf)) > 0) {
  460.         if (buf.ut_name[0] != '\0') {
  461.             count++;
  462.         }
  463.     }
  464.     return (was_users = (count > max_users));
  465. }
  466.  
  467. tod()
  468. {
  469. #ifdef TOD
  470.     long now;
  471.     struct tm *localtime();
  472.     struct tm *ntime;
  473.  
  474.     time(&now);
  475.     ntime = localtime(&now);
  476.     if(ntime->tm_wday == 0 || ntime->tm_wday == 6)
  477.         return(was_tod = FALSE);/* OK on Sat & Sun */
  478.     if(ntime->tm_hour < MORNING || ntime->tm_hour >= EVENING)
  479.         return(was_tod = FALSE);/* OK during non working hours */
  480.     
  481.     return(was_tod = TRUE);
  482. #endif
  483. }
  484.  
  485. checkfor(file)
  486. char *file;
  487. {
  488.     char buf[200];
  489.     FILE *fd, *fopen();
  490.  
  491.     if((fd = fopen(file, "r")) != NULL) {
  492.         fprintf(stderr, "Sorry, no games now...\n");
  493.         while(fgets(buf, sizeof(buf), fd))
  494.             fprintf(stderr, buf);
  495.         fclose(fd);
  496.         return(TRUE);
  497.     }
  498.     return(FALSE);
  499. }
  500. SHAR_EOF
  501. echo shar: extracting "'gr.h'" '(1771 characters)'
  502. if test -f 'gr.h'
  503. then
  504.     echo shar: over-writing existing file "'gr.h'"
  505. fi
  506. cat << \SHAR_EOF > 'gr.h'
  507. /*
  508.  * $Header: gr.h,v 1.3 86/03/25 15:50:31 mcooper Exp $
  509.  *------------------------------------------------------------------
  510.  *
  511.  * $Source: /usr/src/local/gr/RCS/gr.h,v $
  512.  * $Revision: 1.3 $
  513.  * $Date: 86/03/25 15:50:31 $
  514.  * $State: Exp $
  515.  * $Author: mcooper $
  516.  * $Locker: mcooper $
  517.  *
  518.  *------------------------------------------------------------------
  519.  *
  520.  * Michael Cooper (mcooper@usc-oberon.arpa)
  521.  * University Computing Services,
  522.  * University of Southern California,
  523.  * Los Angeles, California,   90089-0251
  524.  * (213) 743-3469
  525.  *
  526.  *------------------------------------------------------------------
  527.  * $Log:    gr.h,v $
  528.  * Revision 1.3  86/03/25  15:50:31  mcooper
  529.  * Moved CONTROL back to normal place in /usr/games/lib.
  530.  * 
  531.  * Revision 1.2  86/03/25  15:47:57  mcooper
  532.  * Lines beginning with '#' are comment lines.
  533.  * 
  534.  * Revision 1.1  86/02/12  17:49:54  mcooper
  535.  * Initial revision
  536.  * 
  537.  *------------------------------------------------------------------
  538.  */
  539.  
  540. /*
  541.  * TOD - define if you wish to restrict game playing during a certain
  542.  *     time of day on weekdays.  Use MORNING and EVENING as the time
  543.  *     period.
  544.  */
  545. /*
  546. #define TOD
  547. */
  548. #define MORNING        8            /* stop playing games */
  549. #define EVENING        17            /* game time starts */
  550.  
  551. /*
  552.  * HIDEDIR - directory where the actual games are kept.
  553.  */
  554. #define HIDEDIR        "/usr/games/.hide"
  555.  
  556. /* 
  557.  * NOGAMING - If this file exists, it's contents are printed out and
  558.  *          gaming is not permitted.
  559.  */
  560. #define NOGAMING    "/usr/games/nogames"    
  561.  
  562. /*
  563.  * LOGFILE - Define to file name to log entries in.
  564.  */
  565. #define LOGFILE        "/usr/games/lib/gr.log"
  566.  
  567. /*
  568.  * CONTROL - Master control file.
  569.  */
  570. #define CONTROL        "/usr/games/lib/gr.control"
  571.  
  572. /*
  573.  * Misc. defines - Leave this alone!
  574.  */
  575. #define TRUE        1
  576. #define FALSE        0
  577. #define COMMENT        '#'
  578. SHAR_EOF
  579. echo shar: extracting "'logfile.c'" '(1757 characters)'
  580. if test -f 'logfile.c'
  581. then
  582.     echo shar: over-writing existing file "'logfile.c'"
  583. fi
  584. cat << \SHAR_EOF > 'logfile.c'
  585. #ifndef lint
  586. static char *RCSid = "$Header: logfile.c,v 1.3 86/03/25 15:44:35 mcooper Exp $";
  587. #endif
  588.  
  589. /*
  590.  *------------------------------------------------------------------
  591.  *
  592.  * $Source: /usr/src/local/gr/RCS/logfile.c,v $
  593.  * $Revision: 1.3 $
  594.  * $Date: 86/03/25 15:44:35 $
  595.  * $State: Exp $
  596.  * $Author: mcooper $
  597.  * $Locker: mcooper $
  598.  *
  599.  *------------------------------------------------------------------
  600.  *
  601.  * Michael Cooper (mcooper@usc-oberon.arpa)
  602.  * University Computing Services,
  603.  * University of Southern California,
  604.  * Los Angeles, California,   90089-0251
  605.  * (213) 743-3469
  606.  *
  607.  *------------------------------------------------------------------
  608.  * $Log:    logfile.c,v $
  609.  * Revision 1.3  86/03/25  15:44:35  mcooper
  610.  * more of same.
  611.  * 
  612.  * Revision 1.2  86/03/25  15:35:43  mcooper
  613.  * New headers...
  614.  * 
  615.  *------------------------------------------------------------------
  616.  */
  617.  
  618. /*
  619.  * logfile() -- log who is playing.  If LOGFILE is defined (in gr.c)
  620.  *        then this function keeps track of users who play.
  621.  */
  622.  
  623.  
  624. #include <stdio.h>
  625. #include <pwd.h>
  626. #include "gr.h"
  627.  
  628. #ifdef LOGFILE
  629. struct passwd *pw;
  630. struct passwd *getpwuid();
  631.  
  632. logfile(msg)
  633. char *msg;
  634. {
  635.     char *fprintf();
  636.     char *strcmp();
  637.     char *getlogin();
  638.     char *time(), *ctime();
  639.     char buf[80];
  640.     char *str;
  641.     char *user;
  642.     double now;
  643.     int diff = 0;
  644.     FILE *fd, *fopen();
  645.  
  646.     if ((pw = getpwuid(getuid())) != NULL)
  647.         user = pw->pw_name;
  648.     else
  649.         user = "(unknown)";
  650.  
  651.     if((str = getlogin()) != NULL)
  652.         if(strcmp(str, user) != 0) {
  653.             diff = 1;
  654.             sprintf(buf, "(%s)", str);
  655.         }
  656.  
  657.     time(&now);
  658.  
  659.     if((fd = fopen(LOGFILE, "a")) != NULL){
  660.         fprintf(fd, "%-10s%-12s%-7s%10.24s  [ %s ]\n", 
  661.                 user, 
  662.                 diff ? buf : "", 
  663.                 rindex(ttyname(0), '/') + 1,
  664.                 ctime(&now), 
  665.                 msg);
  666.         fclose(fd);
  667.     }
  668. }
  669. #endif
  670. SHAR_EOF
  671. #    End of shell archive
  672. exit 0
  673.  
  674.  
  675.